package jnpf.engine.controller;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import jnpf.base.ActionResult;
import jnpf.base.UserInfo;
import jnpf.base.vo.PaginationVO;
import jnpf.constant.MsgCode;
import jnpf.engine.entity.*;
import jnpf.engine.enums.FlowNodeEnum;
import jnpf.engine.enums.FlowRecordEnum;
import jnpf.engine.enums.FlowTaskStatusEnum;
import jnpf.engine.model.flowbefore.FlowBatchModel;
import jnpf.engine.model.flowbefore.FlowBeforeInfoVO;
import jnpf.engine.model.flowbefore.FlowBeforeListVO;
import jnpf.engine.model.flowbefore.FlowSummary;
import jnpf.engine.model.flowcandidate.FlowCandidateUserModel;
import jnpf.engine.model.flowcandidate.FlowCandidateVO;
import jnpf.engine.model.flowengine.FlowModel;
import jnpf.engine.model.flowengine.shuntjson.childnode.ChildNode;
import jnpf.engine.model.flowengine.shuntjson.nodejson.ChildNodeList;
import jnpf.engine.model.flowengine.shuntjson.nodejson.ConditionList;
import jnpf.engine.model.flowmessage.FlowParameterModel;
import jnpf.engine.model.flowtask.FlowTaskListModel;
import jnpf.engine.model.flowtask.PaginationFlowTask;
import jnpf.engine.model.flowtask.TaskNodeModel;
import jnpf.engine.service.*;
import jnpf.engine.util.*;
import jnpf.exception.WorkFlowException;
import jnpf.permission.entity.UserEntity;
import jnpf.util.JsonUtil;
import jnpf.util.RedisUtil;
import jnpf.util.StringUtil;
import jnpf.util.UserProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 待我审核
 *
 * @author JNPF开发平台组
 * @version V3.1.0
 * @copyright 引迈信息技术有限公司
 * @date 2019年9月27日 上午9:18
 */
@Api(tags = "待我审核", value = "FlowBefore")
@RestController
@RequestMapping("/api/workflow/Engine/FlowBefore")
public class FlowBeforeController {


    @Autowired
    private ServiceAllUtil serviceUtil;
    @Autowired
    private UserProvider userProvider;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private FlowTaskUtil flowTaskUtil;
    @Autowired
    private FlowTaskService flowTaskService;
    @Autowired
    private FlowTaskOperatorService flowTaskOperatorService;
    @Autowired
    private FlowTaskOperatorRecordService flowTaskOperatorRecordService;
    @Autowired
    private FlowTaskNodeService flowTaskNodeService;
    @Autowired
    private FlowEngineService flowEngineService;
    @Autowired
    private FlowTaskNewService flowTaskNewService;

    /**
     * 获取待我审核列表
     *
     * @param category           分类
     * @param paginationFlowTask
     * @return
     */
    @ApiOperation("获取待我审核列表(有带分页)，1-待办事宜，2-已办事宜，3-抄送事宜,4-批量审批")
    @GetMapping("/List/{category}")
    public ActionResult list(@PathVariable("category") String category, PaginationFlowTask paginationFlowTask) {
        List<FlowTaskListModel> data = new ArrayList<>();
        if (FlowNature.WAIT.equals(category)) {
            data = flowTaskService.getWaitList(paginationFlowTask);
        } else if (FlowNature.TRIAL.equals(category)) {
            data = flowTaskService.getTrialList(paginationFlowTask);
        } else if (FlowNature.CIRCULATE.equals(category)) {
            data = flowTaskService.getCirculateList(paginationFlowTask);
        } else if (FlowNature.BATCH.equals(category)) {
            data = flowTaskService.getBatchWaitList(paginationFlowTask);
        }
        List<FlowBeforeListVO> listVO = new LinkedList<>();
        List<UserEntity> userList = serviceUtil.getUserName(data.stream().map(t -> t.getCreatorUserId()).collect(Collectors.toList()));
        List<FlowEngineEntity> engineList = flowEngineService.getFlowList(data.stream().map(t -> t.getFlowId()).collect(Collectors.toList()));
        boolean isBatch = FlowNature.BATCH.equals(category);
        for (FlowTaskListModel task : data) {
            FlowBeforeListVO vo = JsonUtil.getJsonToBean(task, FlowBeforeListVO.class);
            //用户名称赋值
            UserEntity user = userList.stream().filter(t -> t.getId().equals(vo.getCreatorUserId())).findFirst().orElse(null);
            vo.setUserName(user != null ? user.getRealName() + "/" + user.getAccount() : "");
            FlowEngineEntity engine = engineList.stream().filter(t -> t.getId().equals(vo.getFlowId())).findFirst().orElse(null);
            if (engine != null) {
                vo.setFormType(engine.getFormType());
            }
            if (isBatch) {
                ChildNodeList childNode = JsonUtil.getJsonToBean(vo.getApproversProperties(), ChildNodeList.class);
                vo.setApproversProperties(JsonUtil.getObjectToString(childNode.getProperties()));
            }
            vo.setFlowVersion(StringUtil.isEmpty(vo.getFlowVersion()) ? "" : "v" + vo.getFlowVersion());
            listVO.add(vo);
        }
        PaginationVO paginationVO = JsonUtil.getJsonToBean(paginationFlowTask, PaginationVO.class);
        return ActionResult.page(listVO, paginationVO);
    }

    /**
     * 获取待我审批信息
     *
     * @param id 主键值
     * @return
     */
    @ApiOperation("获取待我审批信息")
    @GetMapping("/{id}")
    public ActionResult info(@PathVariable("id") String id, String taskNodeId, String taskOperatorId) throws WorkFlowException {
        FlowBeforeInfoVO vo = flowTaskNewService.getBeforeInfo(id, taskNodeId, taskOperatorId);
        return ActionResult.success(vo);
    }

    /**
     * 待我审核审核
     *
     * @param id        待办主键值
     * @param flowModel 流程经办
     * @return
     */
    @ApiOperation("待我审核审核")
    @PostMapping("/Audit/{id}")
    public ActionResult audit(@PathVariable("id") String id, @RequestBody FlowModel flowModel) throws WorkFlowException {
        FlowTaskOperatorEntity operator = flowTaskOperatorService.getInfo(id);
        UserInfo userInfo = userProvider.get();
        flowModel.setUserInfo(userInfo);
        FlowTaskEntity flowTask = flowTaskService.getInfo(operator.getTaskId());
        flowTaskNewService.permissions(operator.getHandleId(), flowTask, operator, "", flowModel);
        if (FlowNature.ProcessCompletion.equals(operator.getCompletion())) {
            String rejecttKey = userInfo.getTenantId() + id;
            if (redisUtil.exists(rejecttKey)) {
                throw new WorkFlowException(MsgCode.WF005.get());
            }
            redisUtil.insert(rejecttKey, id, 10);
            FlowContextHolder.initEvent();
            flowTaskNewService.audit(flowTask, operator, flowModel);
            List<FlowParameterModel> parameterModels = FlowContextHolder.getAllEvent();
            for (FlowParameterModel model : parameterModels) {
                serviceUtil.infoToId(model.getInterId(), model.getParameterMap());
            }
            FlowContextHolder.clearEvent();
            return ActionResult.success("审核成功");
        } else {
            return ActionResult.fail(MsgCode.WF005.get());
        }
    }

    /**
     * 保存草稿
     *
     * @param id 待办主键值
     * @return
     */
    @ApiOperation("保存草稿")
    @PostMapping("/SaveAudit/{id}")
    public ActionResult saveAudit(@PathVariable("id") String id, @RequestBody FlowModel flowModel) throws WorkFlowException {
        FlowTaskOperatorEntity flowTaskOperatorEntity = flowTaskOperatorService.getInfo(id);
        if (flowTaskOperatorEntity != null) {
            FlowTaskEntity flowTaskEntity = flowTaskService.getInfo(flowTaskOperatorEntity.getTaskId());
            FlowEngineEntity engine = flowEngineService.getInfo(flowTaskEntity.getFlowId());
            Map<String, Object> formDataAll = flowModel.getFormData();
            if (FlowNature.CUSTOM.equals(engine.getFormType())) {
                Object data = formDataAll.get("data");
                if (data != null) {
                    formDataAll = JsonUtil.stringToMap(String.valueOf(data));
                }
            }
            flowTaskOperatorEntity.setDraftData(JsonUtil.getObjectToString(formDataAll));
            flowTaskOperatorService.updateById(flowTaskOperatorEntity);
            return ActionResult.success(MsgCode.SU002.get());
        }
        return ActionResult.fail(MsgCode.FA001.get());
    }

    /**
     * 审批汇总
     *
     * @param id       待办主键值
     * @param category 类型
     * @return
     */
    @ApiOperation("审批汇总")
    @GetMapping("/RecordList/{id}")
    public ActionResult recordList(@PathVariable("id") String id, String category, String type) {
        List<FlowSummary> flowSummaries = flowTaskNewService.recordList(id, category, type);
        return ActionResult.success(flowSummaries);
    }

    /**
     * 待我审核驳回
     *
     * @param id 待办主键值
     * @return
     */
    @ApiOperation("待我审核驳回")
    @PostMapping("/Reject/{id}")
    public ActionResult reject(@PathVariable("id") String id, @RequestBody FlowModel flowModel) throws WorkFlowException {
        FlowTaskOperatorEntity operator = flowTaskOperatorService.getInfo(id);
        FlowTaskEntity flowTask = flowTaskService.getInfo(operator.getTaskId());
        UserInfo userInfo = userProvider.get();
        flowModel.setUserInfo(userInfo);
        flowTaskNewService.permissions(operator.getHandleId(), flowTask, operator, "", flowModel);
        if (FlowNature.ProcessCompletion.equals(operator.getCompletion())) {
            String rejecttKey = userInfo.getTenantId() + id;
            if (redisUtil.exists(rejecttKey)) {
                throw new WorkFlowException(MsgCode.WF112.get());
            }
            redisUtil.insert(rejecttKey, id, 10);
            FlowContextHolder.initEvent();
            flowTaskNewService.reject(flowTask, operator, flowModel);
            List<FlowParameterModel> parameterModels = FlowContextHolder.getAllEvent();
            for (FlowParameterModel model : parameterModels) {
                serviceUtil.infoToId(model.getInterId(), model.getParameterMap());
            }
            FlowContextHolder.clearEvent();
            return ActionResult.success("驳回成功");
        } else {
            return ActionResult.fail("已审核完成");
        }
    }

    /**
     * 待我审核转办
     *
     * @param id 主键值
     * @return
     */
    @ApiOperation("待我审核转办")
    @PostMapping("/Transfer/{id}")
    public ActionResult transfer(@PathVariable("id") String id, @RequestBody FlowModel flowModel) throws WorkFlowException {
        FlowTaskOperatorEntity operator = flowTaskOperatorService.getInfo(id);
        FlowTaskEntity flowTask = flowTaskService.getInfo(operator.getTaskId());
        flowModel.setUserInfo(userProvider.get());
        flowTaskNewService.permissions(operator.getHandleId(), flowTask, operator, "", flowModel);
        operator.setHandleId(flowModel.getFreeApproverUserId());
        operator.setCreatorTime(new Date());
        flowTaskNewService.transfer(operator, flowModel);
        return ActionResult.success("转办成功");
    }

    /**
     * 待我审核撤回审核
     * 注意：在撤销流程时要保证你的下一节点没有处理这条记录；如已处理则无法撤销流程。
     *
     * @param id 主键值
     * @return
     */
    @ApiOperation("待我审核撤回审核")
    @PostMapping("/Recall/{id}")
    public ActionResult recall(@PathVariable("id") String id, @RequestBody FlowModel flowModel) throws WorkFlowException {
        FlowTaskOperatorRecordEntity operatorRecord = flowTaskOperatorRecordService.getInfo(id);
        List<FlowTaskNodeEntity> nodeList = flowTaskNodeService.getList(operatorRecord.getTaskId()).stream().filter(t -> FlowNodeEnum.Process.getCode().equals(t.getState())).collect(Collectors.toList());
        FlowTaskNodeEntity taskNode = nodeList.stream().filter(t -> t.getId().equals(operatorRecord.getTaskNodeId())).findFirst().orElse(null);
        if(FlowRecordEnum.revoke.getCode().equals(operatorRecord.getStatus())){
            return ActionResult.fail("撤回失败");
        }
        if (taskNode != null) {
            flowModel.setUserInfo(userProvider.get());
            flowTaskNewService.recall(id, operatorRecord, flowModel);
            return ActionResult.success("撤回成功");
        }
        return ActionResult.fail("撤回失败");
    }

    /**
     * 待我审核终止审核
     *
     * @param id 主键值
     * @return
     */
    @ApiOperation("待我审核终止审核")
    @PostMapping("/Cancel/{id}")
    public ActionResult cancel(@PathVariable("id") String id, @RequestBody FlowModel flowModel) throws WorkFlowException {
        FlowTaskEntity flowTaskEntity = flowTaskService.getInfo(id);
        if (flowTaskEntity != null) {
            if (flowTaskEntity.getFlowType() == 1) {
                return ActionResult.fail("功能流程不能终止");
            }
            flowModel.setUserInfo(userProvider.get());
            flowTaskNewService.cancel(flowTaskEntity, flowModel);
            return ActionResult.success(MsgCode.SU009.get());
        }
        return ActionResult.fail(MsgCode.FA009.get());
    }

    /**
     * 指派人
     *
     * @param id 主键值
     * @return
     */
    @ApiOperation("指派人")
    @PostMapping("/Assign/{id}")
    public ActionResult assign(@PathVariable("id") String id, @RequestBody FlowModel flowModel) throws WorkFlowException {
        flowModel.setUserInfo(userProvider.get());
        flowTaskNewService.assign(id, flowModel);
        return ActionResult.success("指派成功");
    }

    /**
     * 获取候选人
     *
     * @return
     */
    @ApiOperation("获取候选人节点")
    @PostMapping("/Candidates/{id}")
    public ActionResult candidates(@PathVariable("id") String id, @RequestBody FlowModel flowModel) throws WorkFlowException {
        flowModel.setUserInfo(userProvider.get());
        FlowCandidateVO candidate = flowTaskNewService.candidates(id, flowModel, false);
        return ActionResult.success(candidate);
    }

    /**
     * 获取候选人
     *
     * @return
     */
    @ApiOperation("获取候选人")
    @PostMapping("/CandidateUser/{id}")
    public ActionResult candidateUser(@PathVariable("id") String id, @RequestBody FlowModel flowModel) throws WorkFlowException {
        flowModel.setUserInfo(userProvider.get());
        List<FlowCandidateUserModel> candidate = flowTaskNewService.candidateUser(id, flowModel);
        PaginationVO paginationVO = JsonUtil.getJsonToBean(flowModel, PaginationVO.class);
        return ActionResult.page(candidate, paginationVO);
    }

    /**
     * 批量审批引擎
     *
     * @return
     */
    @ApiOperation("批量审批引擎")
    @GetMapping("/BatchFlowSelector")
    public ActionResult batchFlowSelector() {
        List<FlowBatchModel> batchFlowList = flowTaskService.batchFlowSelector();
        return ActionResult.success(batchFlowList);
    }

    /**
     * 引擎节点
     *
     * @param id 主键值
     * @return
     * @throws WorkFlowException
     */
    @ApiOperation("引擎节点")
    @GetMapping("/NodeSelector/{id}")
    public ActionResult nodeSelector(@PathVariable("id") String id) throws WorkFlowException {
        FlowEngineEntity engine = flowEngineService.getInfo(id);
        List<FlowBatchModel> batchList = new ArrayList<>();
        ChildNode childNodeAll = JsonUtil.getJsonToBean(engine.getFlowTemplateJson(), ChildNode.class);
        //获取流程节点
        List<ChildNodeList> nodeListAll = new ArrayList<>();
        List<ConditionList> conditionListAll = new ArrayList<>();
        //递归获取条件数据和节点数据
        FlowJsonUtil.getTemplateAll(childNodeAll, nodeListAll, conditionListAll);
        List<String> type = new ArrayList() {{
            add(FlowNature.NodeSubFlow);
            add(FlowNature.NodeStart);
        }};
        for (ChildNodeList childNodeList : nodeListAll) {
            if (!type.contains(childNodeList.getCustom().getType())) {
                FlowBatchModel batchModel = new FlowBatchModel();
                batchModel.setFullName(childNodeList.getProperties().getTitle());
                batchModel.setId(childNodeList.getCustom().getNodeId());
                batchList.add(batchModel);
            }
        }
        return ActionResult.success(batchList);
    }

    /**
     * 批量审批
     *
     * @return
     * @throws WorkFlowException
     */
    @ApiOperation("批量审批")
    @PostMapping("/BatchOperation")
    public ActionResult batchOperation(@RequestBody FlowModel flowModel) throws WorkFlowException {
        flowModel.setUserInfo(userProvider.get());
        flowTaskNewService.batch(flowModel);
        return ActionResult.success("批量操作完成");
    }

    /**
     * 批量获取候选人
     *
     * @param taskOperatorId 代办数据
     * @return
     * @throws WorkFlowException
     */
    @ApiOperation("批量获取候选人")
    @GetMapping("/BatchCandidate")
    public ActionResult batchCandidate(String flowId, String taskOperatorId) throws WorkFlowException {
        FlowModel flowModel = new FlowModel();
        flowModel.setUserInfo(userProvider.get());
        FlowCandidateVO candidate = flowTaskNewService.batchCandidates(flowId, taskOperatorId, flowModel);
        return ActionResult.success(candidate);
    }

    /**
     * 消息跳转工作流
     *
     * @param id 代办id
     * @return
     * @throws WorkFlowException
     */
    @ApiOperation("消息跳转工作流")
    @GetMapping("/{id}/Info")
    public ActionResult taskOperatorId(@PathVariable("id") String id) throws WorkFlowException {
        FlowTaskOperatorEntity operator = flowTaskOperatorService.getInfo(id);
        FlowTaskEntity flowTask = flowTaskService.getInfo(operator.getTaskId());
        FlowModel flowModel = new FlowModel();
        flowModel.setUserInfo(userProvider.get());
        flowTaskNewService.permissions(operator.getHandleId(), flowTask, operator, "", flowModel);
        return ActionResult.success();
    }

    /**
     * 节点下拉框
     *
     * @return
     */
    @ApiOperation("节点下拉框")
    @GetMapping("/Selector/{taskId}")
    public ActionResult selector(@PathVariable("taskId") String taskId) {
        List<String> nodetype = new ArrayList() {{
            add(FlowNature.NodeStart);
            add(FlowNature.NodeSubFlow);
            add(FlowNature.EndRound);
        }};
        List<FlowTaskNodeEntity> list = flowTaskNodeService.getList(taskId).stream().filter(t -> FlowNodeEnum.Process.getCode().equals(t.getState())).collect(Collectors.toList());
        flowTaskUtil.nodeList(list);
        list = list.stream().filter(t -> !nodetype.contains(t.getNodeType())).collect(Collectors.toList());
        List<TaskNodeModel> nodeList = JsonUtil.getJsonToList(list, TaskNodeModel.class);
        return ActionResult.success(nodeList);
    }

    /**
     * 变更或者复活
     *
     * @return
     */
    @ApiOperation("变更或者复活")
    @PostMapping("/Change")
    public ActionResult change(@RequestBody FlowModel flowModel) throws WorkFlowException {
        FlowTaskEntity info = flowTaskService.getInfo(flowModel.getTaskId());
        if (FlowTaskStatusEnum.Revoke.getCode().equals(info.getStatus()) || FlowTaskStatusEnum.Cancel.getCode().equals(info.getStatus()) || FlowTaskStatusEnum.Draft.getCode().equals(info.getStatus())) {
            throw new WorkFlowException("该流程不能操作");
        }
        flowModel.setUserInfo(userProvider.get());
        flowTaskNewService.change(flowModel);
        String msg = flowModel.getResurgence() ? "复活成功" : "变更成功";
        return ActionResult.success(msg);
    }


}
